package io.forlove.myrtle.files;

import io.forlove.myrtle.event.FileAddEvent;
import io.forlove.myrtle.event.FileDeleteEvent;
import io.forlove.myrtle.event.FileEvent;
import io.forlove.myrtle.event.FileModifyEvent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.io.IOException;
import java.nio.file.*;
import java.util.concurrent.TimeUnit;

@Slf4j
@Component
public class FilesWatcher {

    private WatchService watcher;

    @Autowired
    private ApplicationContext applicationContext;

    @Autowired
    private FileWatchConfigs fileWatchConfigs;

    @PostConstruct
    public void init(){
        try {
             watcher = FileSystems.getDefault().newWatchService();
        Path path = Paths.get(fileWatchConfigs.getDirectory());
        path.register(watcher, StandardWatchEventKinds.ENTRY_CREATE
                ,StandardWatchEventKinds.ENTRY_DELETE
               ,StandardWatchEventKinds.ENTRY_MODIFY
                ,StandardWatchEventKinds.OVERFLOW);

        } catch (IOException e) {
            e.printStackTrace();

        }
    }

    public void watch(){

        while (true) {
            //每隔3秒拉取监听key
            try {
                WatchKey key = watcher.poll(3, TimeUnit.SECONDS);  //等待，超时就返回
                if(key==null){
                    continue;
                }
                for (WatchEvent<?> pollEvent : key.pollEvents()) {

                    WatchEvent.Kind kind = pollEvent.kind();
                    if (kind == StandardWatchEventKinds.OVERFLOW) {
                        continue;
                    }
                    Path path = cast(pollEvent.context());

                    if (kind == StandardWatchEventKinds.ENTRY_DELETE) {
                        log.debug("file delete, type{}  path:{} \n", kind.name(), path);
                        applicationContext.publishEvent(new FileDeleteEvent(this,path.toFile()));
                        continue;
                    }

                    if (kind == StandardWatchEventKinds.ENTRY_CREATE) {
                        log.debug("file add, type:{}  path:{} \n", kind.name(), path);
                        applicationContext.publishEvent(new FileAddEvent(this,path.toFile()));
                        continue;
                    }
                    if (kind == StandardWatchEventKinds.ENTRY_MODIFY) {
                        log.debug("file modify, type:{}  path:{} \n", kind.name(), path);
                        applicationContext.publishEvent(new FileModifyEvent(this,path.toFile()));
                        continue;
                    }

                }
                key.reset();

            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    private Path cast(Object context) {
       return  (Path)(context);
    }


}
